home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / util / pack / xpk_Source.lha / xpk_Source / shell / xPK.c < prev    next >
C/C++ Source or Header  |  1996-12-06  |  9KB  |  396 lines

  1. #define NAME     "xPK"
  2. #define REVISION "3"
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        xPK
  7.     Author:        SDI (before 1.2 Urban Dominik Müller)
  8.     Distribution:    PD
  9.     Description:    General XPK file-to-file packer/unpacker
  10.     Compileropts:    -
  11.     Linkeropts:    -l xpkmaster
  12.  
  13.  1.2   19.10.96 : fixed an recursion error
  14.  1.3   29.11.96 : recompiled
  15. */
  16.  
  17. #include "SDI_defines.h"
  18. #define SDI_TO_ANSI
  19. #include "SDI_ASM_STD_protos.h"
  20. #include <pragma/exec_lib.h>
  21. #include <pragma/dos_lib.h>
  22. #include <pragma/xpkmaster_lib.h>
  23. #include <exec/memory.h>
  24.  
  25. #ifdef __MAXON__
  26.   #define __asm
  27.   #define __saveds
  28. #endif
  29.  
  30. #define lines[1000]
  31.  
  32. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
  33. STRPTR tempname(STRPTR);
  34. STRPTR basename(STRPTR);
  35. void   doarg(STRPTR);
  36. STRPTR dofile(STRPTR, struct FileInfoBlock *);
  37. void   end(STRPTR);
  38. LONG   isexecutable(STRPTR);
  39.  
  40. struct Hook         chunkhook    = {{0}, (ULONG (*) ()) chunkfunc};
  41. struct Library         *XpkBase    = 0;
  42. UBYTE            errbuf[300],
  43.             *err        = 0,
  44.             namebuf[200],
  45.             PrevName[100],
  46.             strbuf[200];
  47. struct FileInfoBlock     *fib        = 0;
  48.  
  49. UBYTE usage[] =
  50. "Usage: XPK [-efrsux] [-m method] [-p password] files\n"
  51. "       -e = extract files (same as -u)\n"
  52. "       -f = force packing of already packed files\n"
  53. "       -m = four letter packing method name\n"
  54. "       -p = encrypt/decrypt using password\n"
  55. "       -r = recursively (un)pack files in dir\n"
  56. "       -s = add suffix and don't delete original\n"
  57. "       -x = pack executables only\n";
  58.  
  59. UBYTE    suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
  60. STRPTR  password = 0, method = 0;
  61.  
  62. void main(int argc, char **argv)
  63. {
  64.   STRPTR c;
  65.   LONG i = 1;
  66.  
  67.   if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
  68.   !(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
  69.     end("Cannot open " XPKNAME "\n");
  70.  
  71.   if(stricmp(basename(argv[0]), "XPK"))
  72.     method = basename(argv[0]);
  73.   else if(argc < 2 || !strcmp (argv[1], "?"))
  74.     end(usage);
  75.  
  76.   for(; *argv[i] == '-'; i++)
  77.     for(c = argv[i] + 1; *c; c++)
  78.     {
  79.       switch (*c)
  80.       {
  81.       case 'p': password = argv[++i]; break;
  82.       case 'm': method = argv[++i]; break;
  83.       case 's': suffix = 1; break;
  84.       case 'f': force = 1; break;
  85.       case 'e':
  86.       case 'u':    unpack = 1; break;
  87.       case 'r': recurse = 1; break;
  88.       case 'x':    executables = 1; break;
  89.       default: end(usage);
  90.       }
  91.       if(i >= argc)
  92.     end(usage);
  93.     }
  94.  
  95.   if(!method && !unpack)
  96.     end("Need a packing method, use -m\n");
  97.  
  98.   if(i == argc)
  99.     end(usage);
  100.  
  101.   for(; i < argc && !err; i++)
  102.     doarg(argv[i]);
  103.  
  104.   end(err);
  105. }
  106.  
  107. void iprint(STRPTR s)
  108. {
  109.   ULONG out = Output(), i;
  110.   for(i = depth; i; --i)
  111.     Write(out, "  ", 2);
  112.   Write(out, s, strlen(s));
  113. }
  114.  
  115. void doarg(STRPTR name)
  116. {
  117.   ULONG lock;
  118.  
  119.   if(*name == 0xFF)
  120.     return;
  121.  
  122.   if(!(lock = Lock(name, ACCESS_READ)))
  123.   {
  124.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  125.     return;
  126.   }
  127.  
  128.   if(!Examine(lock, fib))
  129.   {
  130.     UnLock(lock);
  131.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  132.     return;
  133.   }
  134.  
  135.   if(fib->fib_DirEntryType < 0)
  136.   {
  137.     UnLock(lock);
  138.     dofile(name, fib);
  139.   }
  140.   else if(recurse)
  141.   {
  142.     ULONG prev;
  143.  
  144.     sprintf(strbuf, "Directory %s\n", name);
  145.     iprint(strbuf);
  146.     prev = CurrentDir(lock);
  147.     *PrevName = 0xFF;
  148.  
  149.     while(ExNext(lock, fib) && !err)
  150.     {
  151.       if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  152.     err = " *** Break";
  153.       else
  154.       {
  155.         STRPTR thisname;
  156.     ULONG i = strlen(fib->fib_FileName) + 1;
  157.  
  158.         if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
  159.         {
  160.           Write(Output(), "Not enough memory\n", 18);
  161.           break;
  162.         }
  163.     CopyMem(fib->fib_FileName, thisname, i);
  164.     depth++;
  165.     doarg(PrevName);
  166.     depth--;
  167.     strcpy(PrevName, thisname);
  168.     FreeMem(thisname, i);
  169.       }
  170.     }
  171.     depth++;
  172.     doarg(PrevName);
  173.     depth--;
  174.     *PrevName = 0xFF;
  175.  
  176.     UnLock(CurrentDir(prev));
  177.   }
  178. }
  179.  
  180. STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
  181. {
  182.   struct XpkFib xfib;
  183.   UBYTE buf[100];
  184.   LONG len;
  185.  
  186.   if(!force || unpack)
  187.   {
  188. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  189.       struct TagItem t[] = {        /* and I don't want to use a link */
  190. #else                    /* library */
  191.       if(XpkExamineTags(&xfib,
  192. #endif
  193.     XPK_InName, (ULONG) filename,
  194.     TAG_DONE
  195. #ifdef __MAXON__
  196.       , 0 };
  197.       if(XpkExamine(&xfib, t
  198. #endif
  199.     ))
  200.     {
  201.       sprintf(buf, "Error examining %s\n", filename);
  202.       iprint(buf);
  203.       return 0;
  204.     }
  205.   }
  206.  
  207.   tempname(filename);
  208.   if(!unpack)
  209.   {
  210.     if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
  211.     {
  212.       sprintf(buf, "Skipping (already packed) %s\n", filename);
  213.       iprint(buf);
  214.       return 0;
  215.     }
  216.  
  217.     if(executables && !isexecutable(filename))
  218.       return 0;
  219.  
  220.     if(suffix)
  221.       sprintf(namebuf, "%s.xpk", filename);
  222.  
  223.     {
  224. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  225.       struct TagItem t[] = {        /* and I don't want to use a link */
  226. #else                    /* library */
  227.       if(XpkPackTags(
  228. #endif
  229.         XPK_InName, (ULONG) filename,
  230.     XPK_OutName, (ULONG) namebuf,
  231.     XPK_ChunkHook, (ULONG) &chunkhook,
  232.     XPK_GetError, (ULONG) errbuf,
  233.     XPK_PackMethod, (ULONG) method,
  234.     XPK_Password, (ULONG) password,
  235.     XPK_NoClobber, TRUE,
  236.     TAG_DONE
  237. #ifdef __MAXON__
  238.       , 0 };
  239.       if(XpkPack(t
  240. #endif
  241.       ))
  242.       {
  243.         ULONG i = strlen(errbuf);
  244.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  245.         return err = errbuf;
  246.       }
  247.     }
  248.   }
  249.   else
  250.   {
  251.     if(xfib.xf_Type != XPKTYPE_PACKED)
  252.     {
  253.       sprintf(buf, "Skipping (already unpacked) %s\n", filename);
  254.       iprint(buf);
  255.       return 0;
  256.     }
  257.  
  258.     len = strlen(filename);
  259.     suffix = 0;
  260.     if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
  261.     {
  262.       strcpy(namebuf, filename);
  263.       namebuf[len - 5] = 0;
  264.       suffix = 1;
  265.     }
  266.  
  267.     {
  268. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  269.       struct TagItem t[] = {        /* and I don't want to use a link */
  270. #else                    /* library */
  271.       if(XpkUnpackTags(
  272. #endif
  273.     XPK_InName, (ULONG) filename,
  274.     XPK_FileName, (ULONG) filename,
  275.     XPK_OutName, (ULONG) namebuf,
  276.     XPK_ChunkHook, (ULONG) &chunkhook,
  277.     XPK_Password, (ULONG) password,
  278.     XPK_GetError, (ULONG) errbuf,
  279.     XPK_NoClobber, TRUE,
  280.     TAG_DONE
  281. #ifdef __MAXON__
  282.       , 0 };
  283.       if(XpkUnpack(t
  284. #endif
  285.       ))
  286.       {
  287.         ULONG i = strlen(errbuf);
  288.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  289.         return err = errbuf;
  290.       }
  291.     }
  292.   }
  293.  
  294.   if(!suffix)
  295.   {
  296.     if(!DeleteFile(filename))
  297.       return err = "Cannot delete input file\n";
  298.     if(!Rename(namebuf, filename))
  299.       return err = "Cannot rename tempfile\n";
  300.     if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
  301.       return err = "Cannot set original comment\n";
  302.     if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
  303.       return err = "Cannot set original protection bits\n";
  304.   }
  305. }
  306.  
  307. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
  308. {
  309.   ULONG out = Output();
  310.   UBYTE buf[180];
  311.  
  312.   if(prog->xp_Type == XPKPROG_START)
  313.     Write(out, "\033[0 p", 5);
  314.  
  315.   if(prog->xp_Type != XPKPROG_END)
  316.     sprintf(buf,
  317.          "%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
  318.          prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
  319.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  320.   else
  321.     sprintf(buf,
  322.          "%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
  323.          prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
  324.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  325.  
  326.   iprint(buf);
  327.  
  328.   if(prog->xp_Type == XPKPROG_END)
  329.     Write(out, "\033[1 p", 5);
  330.  
  331.   return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
  332. }
  333.  
  334. STRPTR tempname(STRPTR name)
  335. {
  336.   strcpy(namebuf, name);
  337.   for(name = namebuf + strlen (namebuf); name > namebuf; name--)
  338.     if(name[-1] == '/' || name[-1] == ':')
  339.       break;
  340.   sprintf(name, "tmp%lx", &name);
  341.   return namebuf;
  342. }
  343.  
  344. LONG isexecutable(STRPTR name)
  345. {
  346.   ULONG fh;
  347.   BPTR buf[5];
  348.   UBYTE msg[100];
  349.   LONG len;
  350.  
  351.   if(!(fh = Open(name, MODE_OLDFILE)))
  352.   {
  353.     sprintf(msg, "Cannot open %s\n", name);
  354.     iprint(msg);
  355.     return 0;
  356.   }
  357.   len = Read(fh, (void *) buf, 20);
  358.   Close(fh);
  359.  
  360.   if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
  361.   {
  362.     sprintf(msg, "%s not executable\n", name);
  363.     iprint(msg);
  364.     return 0;
  365.   }
  366.  
  367.   if(buf[3] != 0 || buf[4] + 1 != buf[2])
  368.   {
  369.     sprintf(msg, "%s overlayed\n", name);
  370.     iprint(msg);
  371.     return 0;
  372.   }
  373.   return 1;
  374. }
  375.  
  376. STRPTR basename(STRPTR name)
  377. {
  378.   STRPTR ret = name;
  379.  
  380.   for(; *name; ++name)
  381.   {
  382.     if(*name == ':' || *name == '/')
  383.       ret = name + 1;
  384.   }
  385.   return ret;
  386. }
  387.  
  388. void end(STRPTR text)
  389. {
  390.   if(text)    Write(Output(), text, strlen(text));
  391.   if(XpkBase)    CloseLibrary(XpkBase);
  392.   if(fib)    FreeMem(fib, sizeof(struct FileInfoBlock));
  393.  
  394.   exit(text ? 10 : 0);
  395. }
  396.